﻿using POC.Loggers.Model;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using POC.Reports.Document;
using wlog.Model;
using POC.Azure.Model;
using POC.Azure.Storage;
using Microsoft.WindowsAzure.Storage.Table;

namespace wlog.Shell.Storage.Table
{
    public class TableListCommand : TableStorageCommand
    {
        public override void Setup(string[] args)
        {
            base.Setup(args);
            base.CreateTask(() => { RunCommand(); });
        }
        public OutputChannel RunCommand()
        {
            try
            {
                var tableAPI = GetTableAccount();
                Results.WriteLine("Connected to: {0}", tableAPI.BaseUri);
                var tables = tableAPI.ListTables();
                if (tables.Any())
                {
                    Results.WriteLine("Showing ...{0}", tables.Count());
                    Results.WriteLine("================================================================================");
                    Results.WriteKeyPair("Name", "Uri", 10);
                    Results.WriteLine("================================================================================");
                }
                else
                {
                    Results.WriteLine("There is no table at {0}, would you like to create one ?", tableAPI.BaseUri);
                }
                foreach (var table in tables)
                {
                    Results.WriteKeyPair(table.Name, table.Uri.AbsoluteUri, 10);
                }

            }
            catch (Exception azureEx)
            {
                Results.WriteLine("Error ccreating table {0} ", azureEx.Message);
            }
            return Results;
        }

    }
    public class TableSelectCommand : TableStorageCommand
    {
        string tableName;
        Task _task = null;
        string columns;
        string format;

        string delimiter;

        string location;
        string filePath;
        string[] headers;
        public override void Setup(string[] args)
        {
            base.Setup(args);
            tableName = this.objectName;
            // select table ApplicationLogEntry  "columns=EventID,Message" "location=file" "format=xls" "uri=C:\logs\logentry.xlsx" "delimiter=|" 
            columns = additionalCommands.ContainsKey(K_OPTIONS.objectcolumns) ? additionalCommands[K_OPTIONS.objectcolumns] : string.Empty;
            format = additionalCommands.ContainsKey(K_OPTIONS.objectformat) ? additionalCommands[K_OPTIONS.objectformat].ToLower() : "";

            delimiter = additionalCommands.ContainsKey(K_OPTIONS.objectdelimiter) ? additionalCommands[K_OPTIONS.objectdelimiter].ToLower() : "|";

            location = additionalCommands.ContainsKey(K_OPTIONS.objectlocation) ? additionalCommands[K_OPTIONS.objectlocation].ToLower() : K_LOCATION.inline.ToString();
            filePath = additionalCommands.ContainsKey(K_OPTIONS.objecturi) ? additionalCommands[K_OPTIONS.objecturi] : string.Empty;
            headers = (string.IsNullOrEmpty(columns) || columns == "*") ? null : columns.Split(",".ToArray());

            base.CreateTask(() => { SelectCommand(); });
        }
        public OutputChannel SelectCommand()
        {
            try
            {
                var repo = new TableStorageRespository<ITableEntity>(GetSetUpAccount(), tableName);
                var entries = repo.GetEntries(null);
                //var entries = repo.GetAllEntries();
                Results.WriteLine("Try Table {0} for first to {1} entries.", tableName, 100);
                if (location == K_LOCATION.file.ToString())
                {
                    switch (format)
                    {
                        case "text":
                        case "txt":
                            _task = WriteToTextFile(entries, filePath, delimiter);
                            break;
                        case "xls":
                        case "excel":
                        case "csv":
                        case "xlsx":
                            _task = WriteToExcel(entries, headers, filePath);
                            break;
                        case "xml":
                        case "binary":
                            _task = WriteToXml(entries, filePath);
                            break;
                        default:
                            _task = WriteToConsole(entries);
                            break;
                    }
                }
                else
                {
                     _task = WriteToConsole(entries);
                }
                if (_task != null)
                {
                    _task.RunSynchronously();
                    Results.WriteLine("Table {0} written to {1} in  {2} format.", tableName, filePath, format);
                }

            }
            catch (Exception azureEx)
            {
                Results.WriteLine("Error ccreating table {0} ", azureEx.Message);

            }
            return Results;
        }
        private Task WriteToXml(IEnumerable<ITableEntity> entries, string filePath)
        {
            Task task = new Task(() =>
            {
                var all = new List<object>(entries);
                var table = all.ToTable();
                table.ToFile(filePath);
            });
            return task;
        }
        private Task WriteToExcel(IEnumerable<ITableEntity> entries, string[] columns, string filePath)
        {
            Task task = new Task(() =>
            {
                var all = new List<object>(entries);
                var table = all.ToTable(columns);
                table.ToXLS(filePath);
            });
            return task;
        }
        private Task WriteToTextFile(IEnumerable<ITableEntity> entries, string filePath, string delimiter = "\t")
        {
            Task task = new Task(() =>
            {
                using (StreamWriter file = new StreamWriter(filePath))
                {
                    foreach (var entity in entries)
                    {
                        LogEntry entry = entity as LogEntry;
                        file.WriteLine(Environment.NewLine + entry.ToString(delimiter));
                    }
                }
            });
            return task;
        }
        private Task WriteToConsole(IEnumerable<ITableEntity> entries)
        {
            Task task = new Task(() =>
                {
                    foreach (var entity in entries)
                    {
                        LogEntry entry = entity as LogEntry;
                        Console.WriteLine(entry.ToString(delimiter));
                    }
                });
            return task;
        }

    }
}
